package com.infore.quartz.main.config;

import cn.hutool.json.JSONUtil;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
import com.baomidou.mybatisplus.MybatisConfiguration;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import com.infore.common.datasource.DBDruidProperties;
import com.infore.common.datasource.DynamicDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import tk.mybatis.mapper.common.BaseMapper;
import tk.mybatis.mapper.entity.Config;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.spring.annotation.MapperScan;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 动态数据源注册
 * @author lijianhua
 */
@Configuration
@MapperScan(value = "tk.mybatis.mapper.annotation",
        markerInterface = BaseMapper.class,
        mapperHelperRef = "systemMapperHelper",
        sqlSessionTemplateRef = "systemSqlSessionTemplate"
)
@Slf4j
public class DataSourceConfig {

    @Autowired
    private DBDruidProperties properties;

    @Bean(name = "quartzDataSource")
    public DynamicDataSource quartzDataSource() {
        log.info("quartz数据源,用于quartz默认数据源");
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        System.out.println("QQQ" + JSONUtil.toJsonStr(properties));
        // 添加数据源
        Map<Object, Object> dsMap = new HashMap<>(2);
        dsMap.put("dataMaintain", properties.getDataMaintain());
        dsMap.put("quartzData", properties.getQuartzData());
        dynamicDataSource.setTargetDataSources(dsMap);
        dynamicDataSource.setDefaultTargetDataSource(properties.getQuartzData());
        return dynamicDataSource;
    }


    @Bean(name = "dynamicSource")
    public DynamicDataSource dataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        System.out.println("ZZZ"+ JSONUtil.toJsonStr(properties));
        // 添加数据源
        Map<Object, Object> dsMap = new HashMap<>(2);
        dsMap.put("dataMaintain", properties.getDataMaintain());
        dsMap.put("quartzData", properties.getQuartzData());
        dynamicDataSource.setTargetDataSources(dsMap);
        dynamicDataSource.setDefaultTargetDataSource(properties.getDataMaintain());
        return dynamicDataSource;
    }

    @Bean(name = "systemTransactionManager")
    public DataSourceTransactionManager setTransactionManager(@Qualifier("dynamicSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "systemSqlSessionFactory")
    @Primary
    public SqlSessionFactory setSqlSessionFactory(@Qualifier("dynamicSource") DataSource dataSource) throws Exception {
//        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();//mybatis使用
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();//mybatis-plush使用
        bean.setDataSource(dataSource);
        //   bean.setTypeAliasesPackage("cn.comtom.quartz.model.dbo");
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
//        org.apache.ibatis.session.Configuration conf = new org.apache.ibatis.session.Configuration();//mybatis使用
        MybatisConfiguration conf = new MybatisConfiguration ();//mybatis-plush使用
        conf.setLogImpl(Slf4jImpl.class);
        conf.setJdbcTypeForNull(JdbcType.NULL);
        conf.setMapUnderscoreToCamelCase(true);
        conf.setCacheEnabled(false);
        bean.setConfiguration(conf);
        return bean.getObject();
    }

    @Bean(name = "systemSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate setSqlSessionTemplate(@Qualifier("systemSqlSessionFactory") SqlSessionFactory sqlSessionFactory)  {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean
    public MapperHelper systemMapperHelper() {
        Config config = new Config();
        List<Class> mappers = new ArrayList<>();
        config.setMappers(mappers);
        MapperHelper mapperHelper = new MapperHelper();
        mapperHelper.setConfig(config);
        return mapperHelper;
    }

    /**
     * 下面是druid 监控配置
     * http://ip:端口/${context-path}/druid/login.html
     *
     */

    @Bean
    public ServletRegistrationBean<StatViewServlet> druidServlet() {
        ServletRegistrationBean<StatViewServlet> servletRegistrationBean = new ServletRegistrationBean<StatViewServlet>(new StatViewServlet(), "/druid/*");
        //白名单(多个IP逗号分隔)
        servletRegistrationBean.addInitParameter("allow", "");
        //黑名单(多个IP逗号分隔，如果黑名单deny与白名单allow同时存在，deny优先于allow)
        servletRegistrationBean.addInitParameter("deny", "");
        //用户名
        servletRegistrationBean.addInitParameter("loginUsername", "admin");
        //密码
        servletRegistrationBean.addInitParameter("loginPassword", "admin");
        //是否可以重置Druid监控计数器
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean ;

    }

    /**
     * 注册FilterRegistrationBean
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean druidStatFilter() {
        FilterRegistrationBean bean = new FilterRegistrationBean(new WebStatFilter());
        // 添加过滤规则.
        bean.addUrlPatterns("/*");
        // 添加不需要忽略的格式信息.
        bean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        return bean;
    }


    @Bean
    public DruidStatInterceptor druidStatInterceptor() {
        DruidStatInterceptor dsInterceptor = new DruidStatInterceptor();
        return dsInterceptor;
    }
    @Bean
    @Scope("prototype")
    public JdkRegexpMethodPointcut druidStatPointcut() {
        JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
        //需要监控的类
        pointcut.setPattern("com.infore.quartz.main.controller.*");
        return pointcut;
    }

    /**
     * druid spring监控
     * @param druidStatInterceptor
     * @param druidStatPointcut
     * @return
     */
    @Bean
    public DefaultPointcutAdvisor druidStatAdvisor(DruidStatInterceptor druidStatInterceptor, JdkRegexpMethodPointcut druidStatPointcut) {
        DefaultPointcutAdvisor defaultPointAdvisor = new DefaultPointcutAdvisor();
        defaultPointAdvisor.setPointcut(druidStatPointcut);
        defaultPointAdvisor.setAdvice(druidStatInterceptor);
        return defaultPointAdvisor;
    }

}
